/* global utils echarts */
import SizeObserver from '../SizeObserver';
/**
 * @typedef  LineData
 * @property {String} name 数据名
 * @property {String} value 数据值
 * @property {String} [color] 颜色
 */
/**
 * @param {String} title 标题
 * @param {...LineData} data 数据行
 * @return {string} html文本
 */
export function tipProduct(title,data){
	let body='';
	const len=arguments.length;
	for(let i=1;i<len;++i){
		const data=arguments[i];
		body+='<div class="bear-chartTipLine">'+
			(data.color?'<div style="background:'+data.color+';"></div>':'')+
			data.name+': '+data.value+
			'</div>';
	}
	return '<div>'+arguments[0]+'</div>'+body;
}
/**
 * 产生百分数
 * @param {Number} number 数值
 * @param {Number} [precision] 精度
 * @return {string}
 */
export function percent(number,precision=2){
	return (100*number||0).toFixed(precision)+'%';
}
// 报表的混入对象
export const chartMixin={
	components:{
		SizeObserver
	},
	props:{
		// 图标渲染方式'svg','canvas'
		renderer:{
			type:String,
			default:'canvas'
		},
		// data的名称字段
		nameAttr:{
			type:String,
			default:'name'
		},
		// data的值字段
		valueAttr:{
			type:String,
			default:'value'
		},
		/**
		 * 格式化器
		 * @param {String} val 输入框当前值
		 * @return {String} 格式化以后的值
		 */
		formatter:{
			type:Function,
			default(val){
				return val;
			}
		},
		/**
		 * 扩展提示信息
		 * @typedef ExtendTip
		 * @property {String} name 名称
		 * @property {String} value 值
		 */
		/**
		 * @function 扩展提示生成器
		 * @param {Object} cur
		 * @param {Object[]} all
		 * @return {ExtendTip[]}
		 */
		extendTipper:Function,
		data:Array
	},
	data(){
		/**
		 * 非响应数据
		 * chart
		 * lastWidth
		 * lastHeight
		 * oldChartData
		 * lineSum
		 */
		return {
		};
	},
	computed:{
		tipFormatterFn(){
			return function(extendTipper,format,param){
				const lines=[];
				lines.push({
					name:param.name,
					value:format(param.value),
					color:param.color
				},{
					name:'<div class="bear-space"></div>百分比',
					value:percent(param.value/this.oldChartData.sum)
				});
				if(extendTipper){
					for(const tip of extendTipper(param)){
						lines.push({
							name:'<div class="bear-space"></div>'+tip.name,
							value:tip.value
						});
					}
				}
				return tipProduct('',...lines);
			}.bind(this,this.extendTipper,this.formatter);
		}
	},
	watch:{
		data:{
			handler(){
				this.loadChart();
			},
			deep:true
		},
		$_bear_resetOptionListener(){
			this.resetOption();
		},
		$_bear_loadChartListener(){
			this.loadChart();
		}
	},
	created(){
		this.$_bear_resizeFn=utils.debounced(function(data){
			if(data.width!==this.lastWidth||data.height!==this.lastHeight){
				this.lastWidth=data.width;
				this.lastHeight=data.height;
				this.$_bear_resize(data);
			}
		},150,this);
		this.loadChart=utils.debounced(this.$_bear_loadChart,0,this);
		this.resetOption=utils.debounced(this.$_bear_resetOption,0,this);
	},
	mounted(){
		const chartRef=this.$refs.chart;
		this.lastWidth=chartRef.offsetWidth;
		this.lastHeight=chartRef.offsetHeight;
		this.$_bear_beforeInit();
		this.chart=echarts.init(chartRef,null,{renderer:this.renderer});
		this.$_bear_clickEvent();
		this.loadChart();
	},
	beforeDestroy(){
		this.chart.dispose();
	},
	// 供组件重写的方法
	methods:{
		$_bear_clickEvent(){
			this.chart.on('click',this.$emit.bind(this,'click-chart'));
		},
		$_bear_beforeInit(){},
		$_bear_resize(){},
		$_bear_tipPositionFn(point,params,dom,rect,size){
			const box=this.$refs.chart.getBoundingClientRect();
			const tipSize=size.contentSize;
			let x=point[0]-tipSize[0]/2;
			let y=point[1]-tipSize[1]-10;
			let offset=x+box.left;
			if(offset<0){
				x-=offset;
			}
			offset=x+box.left+tipSize[0]-window.innerWidth;
			if(offset>0){
				x-=offset;
			}
			offset=y+box.top;
			if(offset<0){
				y-=offset;
			}
			return [x,y];
		},
		$_bear_loadChart(){},
		$_bear_resetOption(){}
	}
};
// 带纵轴的报表的混入对象
export const yAxisChartMixin={
	props:{
		// 堆叠字段
		stackAttr:{
			type:String,
			default:'stack'
		},
		// x轴分类名
		xAxis:Array,
		// 单个系列横向的百分占比名称
		xPercent:String,
		// 系列间纵向的百分占比名称
		yPercent:String,
		// 纵轴名称
		axisName:String,
		/**
		 * 纵轴刻度格式化器
		 * @param {String} val 输入框当前值
		 * @return {String} 格式化以后的值
		 */
		axisFormatter:Function,
		// 纵轴最小间隔
		minInterval:{
			type:Number,
			default:0
		},
		// 字体大小
		fontSize:{
			type:Number,
			default:14
		},
		// 是否启用缩放组件
		dataZoom:Boolean
	},
	data(){
		/**
		 * 非响应数据
		 * redundance
		 */
		return {
			splitNumber:5
		};
	},
	computed:{
		tipFormatterFn(){
			return function(extendTipper,xPercent,yPercent,format,params){
				let sum=0;
				for(const param of params){
					sum+=param.value;
				}
				const lines=[];
				for(const param of params){
					const value=param.value;
					lines.push({
						name:param.seriesName,
						value:format(value),
						color:param.color
					});
					if(extendTipper){
						for(const tip of extendTipper(param,params)){
							lines.push({
								name:'<div class="bear-space"></div>'+tip.name,
								value:tip.value
							});
						}
					}
					if(xPercent){
						lines.push({
							name:'<div class="bear-space"></div>'+xPercent,
							value:percent(value/this.oldChartData.lineSum[param.seriesIndex])
						});
					}
					if(yPercent){
						lines.push({
							name:'<div class="bear-space"></div>'+yPercent,
							value:percent(value/sum)
						});
					}
				}
				return tipProduct(params[0].name,...lines);
			}.bind(this,this.extendTipper,this.xPercent,this.yPercent,this.formatter);
		}
	},
	methods:{
		// 初始化前的任务
		$_bear_beforeInit(){
			this.$_bear_calcSplitNumber(this.lastHeight);
			this.$watch('splitNumber',function(){
				this.resetOption();
			});
		},
		/**
		 * 重新计算报表大小
		 * @param {Object} data 当前大小
		 * @param {Number} data.width 宽
		 * @param {Number} data.height 高
		 */
		$_bear_resize(data){
			this.chart.resize();
			this.loadChart();
			this.$_bear_calcSplitNumber(data.height);
		},
		/**
		 * 计算纵轴分段数
		 * @param {Number} height 高
		 */
		$_bear_calcSplitNumber(height){
			this.splitNumber=Math.floor((height-this.redundance)/40);
		},
		/**
		 * @callback SeriesCallback
		 * @param {Object} ele 单个series
		 * @return {Object} 改变后的series
		 */
		/**
		 * 生成series数组
		 * @param {SeriesCallback} callback
		 * @return {Array} series数组
		 */
		$_bear_series(callback){
			const nameAttr=this.nameAttr;
			const valueAttr=this.valueAttr;
			const stackAttr=this.stackAttr;
			const lineSum=[];
			this.oldChartData.lineSum=lineSum;
			return this.data.map(function(ele){
				const data=ele[valueAttr];
				lineSum.push(data.reduce(function(a,b){
					return a+b;
				},0));
				return callback({name:ele[nameAttr],data:data,stack:ele[stackAttr]});
			});
		}
	}
};
